﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Core;
using Windows.UI.Xaml;

namespace WinRTSock.Test
{
    public class ChatPageViewModel : INotifyPropertyChanged
    {
        private WinRTSock_RuntimeComponents_Test.WinRTSockChat utility;
        private CoreDispatcher coreDispatcher;

        private string hostName;
        private string port;
        private string sendFromClient;
        private string sendFromServer;
        private string receivedByClient;
        private string receivedByServer;
        private Visibility startButtonVisibility;
        private Visibility stopButtonVisibility;
        private Visibility connectButtonVisibility;
        private Visibility disconnectButtonVisibility;


        public ChatPageViewModel(CoreDispatcher coreDispatcher)
        {
            this.coreDispatcher = coreDispatcher;

            this.Messages = new ObservableCollection<string>();
            this.HostName = "localhost";
            this.Port = "27015";
            this.ConnectButtonVisibility = Visibility.Visible;
            this.DisconnectButtonVisibility = Visibility.Collapsed;
            this.StartButtonVisibility = Visibility.Visible;
            this.StopButtonVisibility = Visibility.Collapsed;
            this.ConnectCommand = new DelegateCommand(this.onConnect, this.canConnect);
            //this.DisconnectCommand = new DelegateCommand(this.onDisconnect, this.canDisconnect);
            //this.StartCommand = new DelegateCommand(this.onStart, this.canStart);
            //this.StopCommand = new DelegateCommand(this.onStop, this.canStop);
            this.SendFromClientCommand = new DelegateCommand(this.onSendFromClient, this.canSendFromClient);
            //this.SendFromServerCommand = new DelegateCommand(this.onSendFromServer, this.canSendFromServer);

            this.utility = new WinRTSock_RuntimeComponents_Test.WinRTSockChat();
        }


        private void updateMessages(string message)
        {
            var z = this.coreDispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                this.Messages.Add(message);
            });
        }
        private void evaluateCanExecute()
        {
            //this.StartCommand.RaiseCanExecuteChanged();
            //this.StopCommand.RaiseCanExecuteChanged();
            this.ConnectCommand.RaiseCanExecuteChanged();
            //this.DisconnectCommand.RaiseCanExecuteChanged();
            this.SendFromClientCommand.RaiseCanExecuteChanged();
            //this.SendFromServerCommand.RaiseCanExecuteChanged();
        }
        //private bool canStart()
        //{
        //    // Can start if not started. 
        //    return this.StartButtonVisibility == Visibility.Visible;
        //}
        //private void onStart()
        //{
        //    var result = -1;
        //    this.updateMessages("Attempting to start listening on 'server' ...");
        //    Task clientTask = new Task(() =>
        //    {
        //        result = this.utility.CreateAndListen(this.HostName, this.Port);
        //        var z = this.coreDispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        //        {
        //            this.ConnectButtonVisibility = Visibility.Collapsed;
        //            this.DisconnectButtonVisibility = Visibility.Visible;
        //            this.evaluateCanExecute();
        //        });
        //    });
        //    clientTask.Start();
        //    if (result == 0)
        //        this.updateMessages("Start listening on 'server' succeeded");
        //    else
        //        this.updateMessages("Start listening on 'server' failed.");
        //}
        //private bool canStop()
        //{
        //    // Can disconnect if connected. 
        //    return this.StopButtonVisibility == Visibility.Visible;
        //}
        //private void onStop()
        //{
        //    // TODO: Implement this
        //    this.StartButtonVisibility = Visibility.Visible;
        //    this.StopButtonVisibility = Visibility.Collapsed;
        //    this.evaluateCanExecute();
        //}
        private bool canConnect()
        {
            // Can connect if the 'server' has been started. 
            return this.ConnectButtonVisibility == Visibility.Visible;
        }
        private async void onConnect()
        {
            var result = -1;
            this.updateMessages("Attempting to create and connect 'client' socket...");
            Task clientTask = new Task(() =>
            {
                result = this.utility.Start(this.HostName, this.Port);
            });
            clientTask.Start();
            await clientTask.AsAsyncAction();
            if (result == 0)
            {
                this.updateMessages("Create and connect 'client' succeeded.");
                this.ConnectButtonVisibility = Visibility.Collapsed;
                this.DisconnectButtonVisibility = Visibility.Visible;
                this.evaluateCanExecute();
            }
            else
            {
                this.updateMessages("Create and connect 'client' failed.");
            }
        }
        //private bool canDisconnect()
        //{
        //    // Can disconnect if connected. 
        //    return this.DisconnectButtonVisibility == Visibility.Visible;
        //}
        //private void onDisconnect()
        //{
        //    // TODO: Implement this
        //    this.ConnectButtonVisibility = Visibility.Visible;
        //    this.DisconnectButtonVisibility = Visibility.Collapsed;
        //    this.evaluateCanExecute();
        //}
        private bool canSendFromClient()
        {
            // Can start if not started. 
            return this.ConnectButtonVisibility == Visibility.Collapsed;
        }
        private async void onSendFromClient()
        {
            var result = -1;
            this.updateMessages("Attempting to send from 'client' ...");
            Task clientTask = new Task(() =>
            {
                result = this.utility.Send(this.SendFromClient, true);
            });
            clientTask.Start();
            await clientTask.AsAsyncAction();
            if (result == 0)
            {
                this.updateMessages("Send from 'client' succeeded.");
            }
            else
            {
                this.updateMessages("Send from 'client' failed.");
            }

            //this.updateMessages("Receive from 'server' ...");
            //clientTask = new Task(() =>
            //{
            //    result = this.utility.Receive(true);
            //});
            //clientTask.Start();
            //await clientTask.AsAsyncAction();
            //if (result == 0)
            //{
            //    this.updateMessages("Receive from 'server' succeeded.");
            //}
            //else
            //{
            //    this.updateMessages("Receive from 'server' failed.");
            //}
        }
        //private bool canSendFromServer()
        //{
        //    // Can disconnect if connected. 
        //    return this.DisconnectButtonVisibility == Visibility.Visible;
        //}
        //private async void onSendFromServer()
        //{
        //    var result = -1;
        //    this.updateMessages("Attempting to send from 'server' ...");
        //    Task clientTask = new Task(() =>
        //    {
        //        result = this.utility.Send(this.SendFromServer, false);
        //    });
        //    clientTask.Start();
        //    await clientTask.AsAsyncAction();
        //    if (result == 0)
        //    {
        //        this.updateMessages("Send from 'server' succeeded.");
        //    }
        //    else
        //    {
        //        this.updateMessages("Send from 'server' failed.");
        //    }

        //    //this.updateMessages("Receive from 'client' ...");
        //    //clientTask = new Task(() =>
        //    //{
        //    //    result = this.utility.Receive(false);
        //    //});
        //    //clientTask.Start();
        //    //await clientTask.AsAsyncAction();
        //    //if (result == 0)
        //    //{
        //    //    this.updateMessages("Receive from 'client' succeeded.");
        //    //}
        //    //else
        //    //{
        //    //    this.updateMessages("Receive from 'client' failed.");
        //    //}
        //}


        public DelegateCommand ConnectCommand { get; private set; }
        public DelegateCommand DisconnectCommand { get; private set; }
        public DelegateCommand StartCommand { get; private set; }
        public DelegateCommand StopCommand { get; private set; }
        public DelegateCommand SendFromClientCommand { get; private set; }
        public DelegateCommand SendFromServerCommand { get; private set; }
        public ObservableCollection<string> Messages { get; private set; }
        public string HostName
        {
            get { return this.hostName; }
            set
            {
                if (this.hostName == value)
                    return;
                this.hostName = value;
                this.OnPropertyChanged("HostName");
            }
        }
        public string Port
        {
            get { return this.port; }
            set
            {
                if (this.port == value)
                    return;
                this.port = value;
                this.OnPropertyChanged("Port");
            }
        }
        public string SendFromClient
        {
            get { return this.sendFromClient; }
            set
            {
                if (this.sendFromClient == value)
                    return;
                this.sendFromClient = value;
                this.OnPropertyChanged("SendFromClient");
            }
        }
        public string SendFromServer
        {
            get { return this.sendFromServer; }
            set
            {
                if (this.sendFromServer == value)
                    return;
                this.sendFromServer = value;
                this.OnPropertyChanged("SendFromServer");
            }
        }
        public string ReceivedByClient
        {
            get { return this.receivedByClient; }
            set
            {
                if (this.receivedByClient == value)
                    return;
                this.receivedByClient = value;
                this.OnPropertyChanged("ReceivedByClient");
            }
        }
        public string ReceivedByServer
        {
            get { return this.receivedByServer; }
            set
            {
                if (this.receivedByServer == value)
                    return;
                this.receivedByServer = value;
                this.OnPropertyChanged("ReceivedByServer");
            }
        }
        public Visibility ConnectButtonVisibility
        {
            get { return this.connectButtonVisibility; }
            set
            {
                if (this.connectButtonVisibility == value)
                    return;
                this.connectButtonVisibility = value;
                this.OnPropertyChanged("ConnectButtonVisibility");
            }
        }
        public Visibility DisconnectButtonVisibility
        {
            get { return this.disconnectButtonVisibility; }
            set
            {
                if (this.disconnectButtonVisibility == value)
                    return;
                this.disconnectButtonVisibility = value;
                this.OnPropertyChanged("DisconnectButtonVisibility");
            }
        }
        public Visibility StartButtonVisibility
        {
            get { return this.startButtonVisibility; }
            set
            {
                if (this.startButtonVisibility == value)
                    return;
                this.startButtonVisibility = value;
                this.OnPropertyChanged("StartButtonVisibility");
            }
        }
        public Visibility StopButtonVisibility
        {
            get { return this.stopButtonVisibility; }
            set
            {
                if (this.stopButtonVisibility == value)
                    return;
                this.stopButtonVisibility = value;
                this.OnPropertyChanged("StopButtonVisibility");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
